﻿using JNPF.Basics.Logic;
using JNPF.Basics.Models;
using JNPF.Basics.Models.Extend.Dtos.Document;
using JNPF.Utils;
using JNPF.Utils.Controller;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace JNPF.Basics.Controller
{
    /// <summary>
    /// 文档管理
    /// 版 本：V3.0.0
    /// 版 权：引迈信息技术有限公司（https://www.jnpfsoft.com）
    /// 作 者：JNPF开发平台组
    /// 日 期：2017-12-08 
    /// </summary>
    [Route("api/Extend/[controller]")]
    public class DocumentController : BaseApiController
    {
        private DocumentBll documentBll = new DocumentBll();
        private UserBll userBll = new UserBll();

        #region GET
        /// <summary>
        /// 列表（文件夹树）
        /// </summary>
        /// <returns></returns>
        [HttpGet("FolderTree")]
        public async Task<ResponseResult> GetFolderTree()
        {
            var data = (await documentBll.GetFolderList()).MapToList<DocumentFolderTreeOutput>();
            data.Add(new DocumentFolderTreeOutput
            {
                id = "-1",
                fullName = "全部文档",
                parentId = "0",
                icon = "fa fa-folder",
            });
            var treeList = data.ToTree();
            return Success(new { list = treeList });
        }

        /// <summary>
        /// 列表（全部文档）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <param name="parentId">文档层级</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResponseResult> GetAllList([FromQuery] KeywordInput input, string parentId)
        {
            var data = await documentBll.GetAllList(parentId);
            if (!string.IsNullOrEmpty(input.keyword))
            {
                data = data.FindAll(t => t.FullName.Contains(input.keyword));
            }
            return Success(new { list = data.MapToList<DocumentListOutput>() });
        }

        /// <summary>
        /// 列表（我的分享）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        [HttpGet("Share")]
        public async Task<ResponseResult> GetShareOutList([FromQuery] KeywordInput input)
        {
            var data = await documentBll.GetShareOutList();
            if (!string.IsNullOrEmpty(input.keyword))
            {
                data = data.FindAll(t => t.FullName.Contains(input.keyword));
            }
            return Success(new { list = data.MapToList<DocumentShareOutput>() });
        }

        /// <summary>
        /// 列表（共享给我）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        [HttpGet("ShareTome")]
        public async Task<ResponseResult> GetShareTomeList([FromQuery] KeywordInput input)
        {
            var data = await documentBll.GetShareTomeList();
            if (!string.IsNullOrEmpty(input.keyword))
            {
                data = data.FindAll(t => t.FullName.Contains(input.keyword));
            }
            var output = data.MapToList<DocumentShareTomeOutput>();
            output.ForEach(x => x.creatorUserId = userBll.GetUserName(x.creatorUserId));
            return Success(new { list = output });
        }

        /// <summary>
        /// 列表（回收站）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        [HttpGet("Trash")]
        public async Task<ResponseResult> GetTrashList([FromQuery] KeywordInput input)
        {
            var data = await documentBll.GetTrashList();
            if (!string.IsNullOrEmpty(input.keyword))
            {
                data = data.FindAll(t => t.FullName.Contains(input.keyword));
            }
            return Success(new { list = data.MapToList<DocumentTrashOutput>() });
        }

        /// <summary>
        /// 列表（共享人员）
        /// </summary>
        /// <param name="documentId">文档主键</param>
        /// <returns></returns>
        [HttpGet("ShareUser/{documentId}")]
        public async Task<ResponseResult> GetShareUserList(string documentId)
        {
            var data = (await documentBll.GetShareUserList(documentId)).MapToList<DocumentShareUserOutput>();
            return Success(new { list = data });
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<ResponseResult> GetInfo(string id)
        {
            var data = await documentBll.GetInfo(id);
            return Success(data.MapTo<DocumentInfoOutput>());
        }
        #endregion

        #region POST
        /// <summary>
        /// 新建
        /// </summary>
        /// <param name="input">实体对象</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResponseResult> Create([FromBody] DocumentCrInput input)
        {
            if (await documentBll.IsExistByFullName(input.fullName, null))
            {
                return Error("名称已存在");
            }
            var entity = input.MapTo<DocumentEntity>();
            await documentBll.Create(entity);
            return Success("新建成功");
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="input">实体对象</param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public async Task<ResponseResult> Update(string id, [FromBody] DocumentUpInput input)
        {
            if (await documentBll.IsExistByFullName(input.fullName, id))
            {
                return Error("名称已存在");
            }
            var entity = input.MapTo<DocumentEntity>();
            await documentBll.Update(id, entity);
            return Success("更新成功");
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task<ResponseResult> Delete(string id)
        {
            var entity = await documentBll.GetInfo(id);
            if (entity != null)
            {
                await documentBll.Delete(entity);
            }
            return Success("删除成功");
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <returns></returns>
        [HttpPost("Uploader")]
        public async Task<ResponseResult> Uploader()
        {
            #region 上传图片
            Thread.Sleep(1000);
            var httpContext = Utils.HttpContext.Current;
            var file = httpContext.Request.Form.Files[0];
            var fileType = Path.GetExtension(file.FileName).Replace(".", "");
            if (!this.AllowFileType(fileType))
                return Error("上传失败，文件格式不允许上传");
            //保存的文件名（为防止特殊文件名）
            var name = CommonHelper.Guid + Path.GetExtension(file.FileName);
            var path = ConfigurationKey.DocumentFilePath + name;
            using (var stream = new FileStream(path, FileMode.Create))
            {
                file.CopyTo(stream);
            }
            #endregion

            #region 保存数据
            var entity = new DocumentEntity();
            entity.Type = 1;
            entity.FullName = file.FileName;
            entity.ParentId = httpContext.Request.Form["parentId"].ToString();
            entity.FileExtension = fileType;
            entity.FilePath = name;
            entity.FileSize = file.Length.ToString();
            entity.DeleteMark = 0;
            await documentBll.Create(entity);
            #endregion
            return Success("上传成功");
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="id">主键值</param>
        [HttpPost("Download/{id}")]
        public async Task<ResponseResult> Download(string id)
        {
            var userinfo = UserProvider.Instance.Get();
            var entity = await documentBll.GetInfo(id);
            if (entity != null)
            {
                var fileName = userinfo.Id + "|" + entity.FilePath + "|document";
                var output = new
                {
                    name = entity.FullName,
                    url = "/api/Common/Download?encryption=" + fileName
                };
                return Success(output);
            }
            return Error("文件不存在");
        }

        /// <summary>
        /// 回收站（彻底删除）
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpDelete("Trash/{id}")]
        public async Task<ResponseResult> TrashDelete(string id)
        {
            await documentBll.TrashDelete(id);
            return Success("删除成功");
        }

        /// <summary>
        /// 回收站（还原文件）
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpPost("Trash/{id}/Actions/Recovery")]
        public async Task<ResponseResult> TrashRecovery(string id)
        {
            await documentBll.TrashRecovery(id);
            return Success("还原成功");
        }

        /// <summary>
        /// 共享文件（创建）
        /// </summary>
        /// <param name="id">共享文件id</param>
        /// <param name="input">共享人</param>
        /// <returns></returns>
        [HttpPost("{id}/Actions/Share")]
        public async Task<ResponseResult> ShareCreate(string id, [FromBody] DocumentActionsShareInput input)
        {
            var userIds = input.userId.Split(",");
            await documentBll.ShareCreate(id, userIds);
            return Success("操作成功");
        }

        /// <summary>
        /// 共享文件（取消）
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpDelete("{id}/Actions/Share")]
        public async Task<ResponseResult> ShareCancel(string id)
        {
            await documentBll.ShareCancel(id);
            return Success("操作成功");
        }

        /// <summary>
        /// 文件/夹移动到
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="toId">将要移动到Id</param>
        /// <returns></returns>
        [HttpPut("{id}/Actions/MoveTo/{toId}")]
        public async Task<ResponseResult> MoveTo(string id, string toId)
        {
            await documentBll.MoveTo(id, toId);
            return Success("操作成功");
        }
        #endregion

        #region Method
        /// <summary>
        /// 允许文件类型
        /// </summary>
        /// <param name="fileExtension">文件后缀名</param>
        /// <returns></returns>
        private bool AllowFileType(string fileExtension)
        {
            var isOk = false;
            var allowExtension = ConfigurationKey.AllowUploadFileType;
            foreach (var item in allowExtension)
            {
                if (item == fileExtension)
                {
                    isOk = true;
                    break;
                }
                else
                {
                    isOk = false;
                }
            }
            return isOk;
        }
        #endregion
    }
}
